package com.heima.comment.service.impl;

import com.heima.comment.feign.UserFeign;
import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vo.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.threadlocal.AppThreadLocalUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@SuppressWarnings("ALL")
/**
 * @Description :
 * @author     :LD
 */
@Service
public class CommentServiceImpl implements CommentService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private UserFeign userFeign;
    @Autowired
    private GreenTextScan greenTextScan;
    @Autowired
    private CommentHotService commentHotService;

    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        //1 检查参数
        if (dto.getArticleId()==null||dto.getContent()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        if (dto.getContent()!=null && dto.getContent().length()>140){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"评论内容不能超过140字");
        }
        //2 登录判断
        ApUser apUser = AppThreadLocalUtils.getUser();
        if (apUser==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //3 安全过滤
        boolean flag = true;
        try {
            Map map = greenTextScan.greeTextScan(dto.getContent());
            if (map.get("suggestion").equals("block")){
                flag = false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        }
        if (!flag){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"评论内容存在敏感词汇");
        }
        //4 保存评论
        ApUser user = userFeign.findUserById(apUser.getId().longValue());
        if (user==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE,"当前登录信息有误");
        }
        ApComment apComment = new ApComment();
        apComment.setContent(dto.getContent());
        apComment.setAuthorId(user.getId());
        apComment.setAuthorName(user.getName());
        apComment.setEntryId(dto.getArticleId());
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        apComment.setImage(user.getImage());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setType((short) 0);
        apComment.setFlag((short) 0);
        mongoTemplate.insert(apComment);

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult like(CommentLikeDto dto) {
        //1 检查参数
        if (dto.getCommentId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //2 判断登录
        ApUser user = AppThreadLocalUtils.getUser();
        if (user==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //3 点赞操作
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        if (apComment!=null&&dto.getOperation()==0){
            //更新点赞数
            apComment.setLikes(apComment.getLikes()+1);
            mongoTemplate.save(apComment);

            //计算热点评论
            if (apComment.getFlag().shortValue()==0 && apComment.getLikes()>=5){
                commentHotService.findHotComment(apComment.getEntryId(),apComment);
            }

            //保存 app评论信息点赞
            ApCommentLike apCommentLike = new ApCommentLike();
            apCommentLike.setAuthorId(user.getId());
            apCommentLike.setCommentId(apComment.getId());
            mongoTemplate.save(apCommentLike);
        }else if (apComment!=null && dto.getOperation()==1){
            //取消点赞
            apComment.setLikes(apComment.getLikes()<0?0:apComment.getLikes()-1);
            mongoTemplate.save(apComment);
            //更新 APP评论信息点赞
            mongoTemplate.remove(Query.query(Criteria.where("authorId").is(user.getId())
                    .and("commentId").is(apComment.getId())),ApComment.class);
        }
        //5.数据返回
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("likes",apComment.getLikes());
        return ResponseResult.okResult(resultMap);
    }

    @Override
    public ResponseResult findByArticleId(CommentDto dto) {
        //1 检查参数
        if (dto.getArticleId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        if (dto.getSize()==null||dto.getSize()==0){
            dto.setSize(20);
        }

        //2.查询当前文章的评论
        List<ApComment> list;
        if (dto.getIndex()!=null && dto.getIndex()==1){//首页
            Query query = Query.query(Criteria.where("entryId").is(dto.getArticleId())
                    .and("flag").is(1)).with(Sort.by(Sort.Direction.DESC,"likes"));
            list = mongoTemplate.find(query, ApComment.class);
            if (list!=null && list.size()>0){//有热点数据
                dto.setSize(dto.getSize()-list.size());
                Query query1 = Query.query(Criteria.where("entryId").is(dto.getArticleId())
                        .and("flag").is(0).and("createdTime").lt(dto.getMinDate()))
                        .limit(dto.getSize())
                        .with(Sort.by(Sort.Direction.DESC,"createdTime"));
                List<ApComment> apComments1 = mongoTemplate.find(query1, ApComment.class);
                list.addAll(apComments1);
            }else {//没有热点数据
                Query query2 = Query.query(Criteria.where("entryId").is(dto.getArticleId())
                        .and("flag").is(0).and("createdTime").lt(dto.getMinDate()))
                        .limit(dto.getSize()).with(Sort.by(Sort.Direction.DESC, "createdTime"));
                list = mongoTemplate.find(query2, ApComment.class);
            }
        }else {//不是首页
            Query query2 = Query.query(Criteria.where("entryId").is(dto.getArticleId())
                    .and("flag").is(0).and("createdTime").lt(dto.getMinDate()))
                    .limit(dto.getSize()).with(Sort.by(Sort.Direction.DESC, "createdTime"));
            list = mongoTemplate.find(query2, ApComment.class);
        }
        //3.数据封装返回
        //3.1 用户未登录 加载数据
        ApUser user = AppThreadLocalUtils.getUser();
        if (user==null){
            return ResponseResult.okResult(list);
        }
        //3.2 用户已登录，加载数据，需要判断当前用户点赞了哪些评论
        List<String> idList = list.stream().map(x -> x.getId()).collect(Collectors.toList());
        Query query1 = Query.query(Criteria.where("commentId").in(idList)
                .and("authorId").is(user.getId()));
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(query1, ApCommentLike.class);

        List<ApCommentVo> resultList = new ArrayList<>();
        if (list!=null && apCommentLikes!=null){
            list.stream().forEach(x->{
                ApCommentVo apCommentVo = new ApCommentVo();
                BeanUtils.copyProperties(x, apCommentVo);
                for (ApCommentLike apCommentLike : apCommentLikes) {
                    if (x.getId().equals(apCommentLike.getCommentId())) {
                        apCommentVo.setOperation((short) 0);
                        break;
                    }
                }
                resultList.add(apCommentVo);
            });
            return ResponseResult.okResult(resultList);
        }else {
            return ResponseResult.okResult(list);
        }
    }
}
